package com.gxitsky.async.design.controller;

import com.gxitsky.async.design.listener.ServletAsyncListener;
import com.gxitsky.utils.JSON;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Nullable;
import javax.servlet.AsyncContext;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.concurrent.*;

/**
 * @author gxing
 * @desc Controller基类
 * @date 2022/7/28
 */
public abstract class BaseController {

    private static ExecutorService exececutor;
    private static final int corePoolSize = 5;
    private static final int maximumPoolSize = 200;
    private static final int keepAliveTime = 10 * 1000;
    private static final int maxQueueTask = 5 * 1000;
    private static final long TIME_OUT = 10 * 1000;

    static {
        exececutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime,
                TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(maxQueueTask));
    }

    public void process(@Nullable Object params, Callable callable) {
        RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
        HttpServletRequest httpServletRequest = ((ServletRequestAttributes) requestAttributes).getRequest();
        AsyncContext asyncContext = httpServletRequest.startAsync();
        new Thread(() -> {
            System.out.println("异步线程启动:" + Thread.currentThread().getName());
            PrintWriter writer = null;
            try {
//                Thread.sleep(8000);
                ServletResponse response = asyncContext.getResponse();
                response.setContentType("application/json;charset=UTF-8");
                writer = response.getWriter();
                HashMap<String, Object> map = new HashMap<>();
                map.put("id", 100L);
                map.put("message", "Hello World!");
                writer.println(JSON.toJsonString(map));
                asyncContext.complete();
                System.out.println("异步线程结束");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();

    }

    /**
     * @param servletRequest 请求
     * @param callable       业务
     * @desc 统一异步处理业务
     * @author gxing
     * @date 2022/7/30 16:35
     */
    public <T> void handler(HttpServletRequest servletRequest, Callable<T> callable) {
//        System.out.println("----------------------------------------------");
//        System.out.println("主线程开始:" + Thread.currentThread().getName() + ":" + DateUtil.format(new Date(), DateUtil.PATTERN_YMDHMS_SLASH));
        AsyncContext asyncContext = servletRequest.startAsync();
        asyncContext.setTimeout(TIME_OUT);
        asyncContext.addListener(new ServletAsyncListener());
        exececutor.execute(() -> {
//            System.out.println("异步线程开启:" + Thread.currentThread().getName());
            try {
//                Thread.sleep(5000);
                T result = callable.call();
                ServletResponse response = asyncContext.getResponse();
                response.setContentType("application/json;charset=UTF-8");
                PrintWriter writer = response.getWriter();
                writer.println(JSON.toJsonString(result));
            } catch (Exception e) {
                throw new RuntimeException(e);
            } finally {
                asyncContext.complete();
            }
//            System.out.println("异步线程结束:" + Thread.currentThread().getName());
        });
//        System.out.println("主线程结束:" + DateUtil.format(new Date(), DateUtil.PATTERN_YMDHMS_SLASH));
    }
}
